﻿using System;
using System.Text;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using System.Globalization;
using System.Net;
using System.Security.Cryptography;

namespace MrBrooks.Utility
{
    /// <summary>
    /// 工具集
    /// </summary>
    [Serializable]
    public static class Utils
    {
        /// <summary>
        /// 赔率已改变的提示代码:-9
        /// </summary>
        public const int ODDS_CHANGED_CODE = -9;

        /// <summary>
        /// 北京时间 ，UTC时间+8
        /// </summary>
        public const int UTC_TIME_ZONE = 8;

        /// <summary>
        /// 执行成功，提示代码：0
        /// </summary>
        public const int SUCCESS_CODE = 0;

        /// <summary>
        /// 将UTC时间转换为北京时间，并格式化为("yyyy-MM-dd HH:mm:ss"),格式
        /// </summary>
        /// <param name="utcTime"></param>
        /// <returns></returns>
        public static string TransUtcToStringTime(DateTime utcTime)
        {
            return utcTime.AddHours(UTC_TIME_ZONE).ToString("yyyy-MM-dd HH:mm:ss");
        }

        /// <summary>
        /// 检测值是否存在
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool CheckExists(int source, params int[] target)
        {
            foreach (var t in target)
            {
                if (source == t) return true;
            }
            return false;
        }

        /// <summary>
        /// 是否有空参数
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool CheckExistsEmpty(params string[] source)
        {
            foreach (var t in source)
            {
                if (string.IsNullOrWhiteSpace(t)) return true;
            }

            return false;
        }

        /// <summary>
        /// 检测是否含有空对象
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool CheckExistsNull(params object[] source)
        {
            foreach (var tmp in source)
            {
                if (tmp == null) return true;
            }

            return false;
        }

        /// <summary>
        /// 检查是否所有参数都为正整数
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool CheckPositive(params int[] source)
        {
            foreach (var tmp in source)
            {
                if (tmp <= 0) return false;
            }

            return true;
        }

        #region .格式化.
        /// <summary>
        /// 格式化
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        private static string FormatNumber3(decimal number)
        {
            return String.Format("{0:n3}", number);
        }

        /// <summary>
        /// 格式化
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        private static string FormatNumber2(decimal number)
        {
            return String.Format("{0:N2}", number);
        }
        #endregion

        #region .与JAVA数据交换.
        /// <summary>
        /// 将Boolean转为字符串
        /// </summary>
        /// <param name="flag"></param>
        /// <returns></returns>
        public static string FormatData(bool flag)
        {
            return flag.ToString();
        }

        /// <summary>
        /// 将int转为字符串
        /// </summary>
        /// <param name="flag"></param>
        /// <returns></returns>
        public static string FormatData(int number)
        {
            return number.ToString();
        }

        /// <summary>
        /// 将DateTime转为字符串
        /// </summary>
        /// <param name="datetime"></param>
        /// <returns></returns>
        public static string FormatData(DateTime datetime)
        {
            return datetime.ToString("yyyy-MM-dd hh:mm:ss");
        }

        /// <summary>
        /// 布尔
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static bool ParseBoolean(string param)
        {
            return (!string.IsNullOrEmpty(param)) && param.Equals("true", StringComparison.OrdinalIgnoreCase);
        }

        /// <summary>
        /// 数字
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static int ParseInt(string param)
        {
            return int.Parse(param);
        }

        /// <summary>
        /// 数字
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static decimal ParseDecimal(string param)
        {
            return decimal.Parse(param);
        }

        /// <summary>
        /// 检测数据日期是否合法
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static bool CheckDateValid(string param)
        {
            if (!Regex.IsMatch(param, @"\d{8}")) return false;
            int day = int.Parse(param);
            DateTime dt = DateTime.MinValue;
            if (DateTime.TryParseExact(param, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out dt))
            {
                return dt.Year >= 2000 && dt.Year < 2200;
            }

            return false;
        }

        /// <summary>
        /// 解析数字型日期
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static DateTime ParseDate(string param)
        {
            DateTime dt = DateTime.MinValue;
            DateTime.TryParseExact(param, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out dt);
            return dt;
        }
        #endregion

        /// <summary>
        /// 标准Md5
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string Md5Normal(string source)
        {
            MD5CryptoServiceProvider hashmd5;
            hashmd5 = new MD5CryptoServiceProvider();
            return BitConverter.ToString(hashmd5.ComputeHash(Encoding.Default.GetBytes(source))).Replace("-", "").ToLower();
        }

        /// <summary>
        /// 获取客户端IP和端口号
        /// </summary>
        /// <param name="socket"></param>
        /// <returns></returns>
        public static string GetIP(Socket socket)
        {
            try
            {
                if (socket != null)
                {
                    var remote = (IPEndPoint)socket.RemoteEndPoint;
                    var address = string.Format("{0}:{1}", remote.Address, remote.Port);
                    return address;
                }
            }
            catch { }

            return string.Empty;
        }

        /// <summary>
        /// 实现 Contains 的模糊查询
        /// </summary>
        /// <param name="source"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool ContainsKey(this string source, string key)
        {
            return source.ToUpper().Contains(key.ToUpper());
        }

        #region .随机数序列.
        private static string[] randomChars = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
        private static int randomCharsLength = randomChars.Length;
        //private static Random random = new Random(int.Parse(DateTime.Now.ToString("smHd")));
        private static int randomSeed = Guid.NewGuid().GetHashCode();
        private static Random random = new Random(randomSeed);

        /// <summary>
        /// 产生固定长度的随机字符串
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string RandomKey(int length)
        {
            int len = randomCharsLength;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < length; i++)
            {
                int idx = random.Next(0, len);
                sb.Append(randomChars[idx]);
            }

            return sb.ToString();
        }

        /// <summary>
        /// 随机长度的随机数
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public static string RandomKey(int start, int end)
        {
            var length = random.Next(start, end);
            return RandomKey(length);
        }
        #endregion

        #region .可逆加解密.
        /// <summary>
        /// 简单的可逆加密
        /// </summary>
        /// <param name="source"></param>
        /// <param name="secretKey"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string EncryptSimple(string source, string secretKey, string encoding = "UTF-8")
        {
            StringBuilder sb = new StringBuilder();
            byte[] sourceBytes = Encoding.GetEncoding(encoding).GetBytes(source);
            byte[] keyBytes = Encoding.GetEncoding(encoding).GetBytes(secretKey);
            int j = 0;
            foreach (byte b in sourceBytes)
            {
                if (j == keyBytes.Length)
                {
                    j = 0;
                }
                sb.AppendFormat("{0:X2}", b ^ keyBytes[j]);
                j++;
            }

            return sb.ToString();
        }

        /// <summary>
        /// 简单的可逆解密
        /// </summary>
        /// <param name="source"></param>
        /// <param name="secretKey"></param>
        /// <returns></returns>
        public static string DecryptSimple(string source, string secretKey, string encoding = "UTF-8")
        {
            try
            {
                int sourceLength = source.Length / 2;
                byte[] sourceBytes = new byte[sourceLength];
                byte[] keyBytes = Encoding.GetEncoding(encoding).GetBytes(secretKey);
                int length = keyBytes.Length;
                int j = 0;
                for (int i = 0; i < sourceLength; i++)
                {
                    if (j == length)
                    {
                        j = 0;
                    }

                    byte b = (byte)Convert.ToInt16(source.Substring(i * 2, 2), 16);
                    sourceBytes[i] = (byte)(b ^ keyBytes[j]);
                    j++;
                }

                return Encoding.GetEncoding(encoding).GetString(sourceBytes, 0, sourceBytes.Length);
            }
            catch
            {
                return "";
            }
        }
        #endregion
    }
}
